package com.asambleacristiana.bean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;

import org.apache.commons.lang3.StringUtils;

import com.asambleacristiana.domain.Cuenta;
import com.asambleacristiana.domain.TipoComprobanteEnum;
import com.asambleacristiana.domain.Movimiento;
import com.asambleacristiana.domain.TipoOperacionEnum;
import com.asambleacristiana.domain.Zona;
import com.asambleacristiana.repository.dao.DAOFactoryJPA;
import com.asambleacristiana.utils.Commons;
import com.asambleacristiana.utils.Saldo;

@ManagedBean
@ViewScoped
public class AdmConsultasBean extends Commons implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private List<Movimiento> movimientos = null;
	private List<Movimiento> movimientosUltimaFecha = null;
	private List<Zona> zonasAsociadas = null;
	private Date fechaDesde;
	private Date fechaHasta;
	private Integer codZonaActual = null;
	private static final Integer TODAS_LAS_ZONAS = -1;
	private Saldo saldo;
	private Saldo saldoCaja;

	// Modificacion y baja de movimientos
	private Long codMovimiento = 0L;
	private Long codMovimientoMod = 0L;
	private String mensaje;
	private Double importe = 0D;
	private Date fecha = null;
	private String detalle = null;
	private Integer codZonaMov;
	private List<Cuenta> cuentas = null;
	private Integer cuentaCod;
	private String nroFactura1;
	private String nroFactura2;
	private TipoComprobanteEnum tipoFactura;
	private String cuit;
	private Movimiento movimiento;

	@PostConstruct
	public void postContruct() {
		zonasAsociadas = getUsuarioLogueado().getZonaSeleccionada().getZonasAsociadas();
		movimientos = new ArrayList<Movimiento>();
		saldo = new Saldo(movimientos);
		movimientosUltimaFecha = new ArrayList<Movimiento>();
		saldoCaja = new Saldo(movimientosUltimaFecha);
	}

	public SelectItem[] getTiposFacturas() {
		SelectItem[] items = new SelectItem[TipoComprobanteEnum.values().length];
		int i = 0;
		for (TipoComprobanteEnum g : TipoComprobanteEnum.values()) {
			items[i++] = new SelectItem(g, g.getTipo());
		}
		return items;
	}

	public String doConsultar() {

		if (fechaDesde.compareTo(fechaHasta) > 0) {

			FacesContext.getCurrentInstance().addMessage(
					null,
					new FacesMessage(FacesMessage.SEVERITY_ERROR, "La fecha desde debe ser menor a la fecha hasta.",
							"La fecha desde debe ser menor a la fecha hasta."));

		} else {
			if ((TODAS_LAS_ZONAS).equals(codZonaActual)) {
				movimientos = DAOFactoryJPA.getInstance().getMovimientoDAO().find(fechaDesde, fechaHasta, getUsuarioLogueado().getAllZonas());
				Date fechaDesde = DAOFactoryJPA.getInstance().getMovimientoDAO().getMinFecha(getUsuarioLogueado().getAllZonas());
				movimientosUltimaFecha = DAOFactoryJPA.getInstance().getMovimientoDAO().find(fechaDesde, fechaHasta, getUsuarioLogueado().getAllZonas());
			
			
			} else {
				movimientos = DAOFactoryJPA.getInstance().getMovimientoDAO().find(codZonaActual, fechaDesde, fechaHasta);
				Date fechaDesde = DAOFactoryJPA.getInstance().getMovimientoDAO().getMinFecha(codZonaActual);
				movimientosUltimaFecha = DAOFactoryJPA.getInstance().getMovimientoDAO().find(codZonaActual, fechaDesde, fechaHasta);
			}

			saldo = new Saldo(movimientos);
			saldoCaja = new Saldo(movimientosUltimaFecha);
		}
		return "";

	}

	public void doBorrar() {
		Movimiento movimiento = DAOFactoryJPA.getInstance().getMovimientoDAO().findById(codMovimiento);
		setMensaje("¿Está seguro de eliminar el movimiento: " + movimiento.toString() + "?");
		codMovimientoMod = 0L;
	}

	private String getNroFactura(String nroFac1, String nroFac2) {
		String nroFactura = null;
		if (!StringUtils.isBlank(nroFac1) && !StringUtils.isBlank(nroFac2)) {
			nroFactura = nroFactura1 + nroFactura2;
		}
		return nroFactura;
	}

	public void doModificar() {
		movimiento = DAOFactoryJPA.getInstance().getMovimientoDAO().findById(codMovimientoMod);
		setMensaje("Ingrese los nuevos valores para el movimiento: " + movimiento.toString());
		importe = movimiento.getImporte();
		fecha = movimiento.getFecha();
		detalle = movimiento.getDetalle();
		codZonaMov = movimiento.getZona().getCodigo();
		cuentas = movimiento.getTipoOperacion().getCuentas();
		if (movimiento.getTipoOperacion().getCodigo().equals(TipoOperacionEnum.ingreso.getCodigo())) {
			cuentaCod = movimiento.getDesde().getCodigo();
		} else {
			cuit = movimiento.getNroCuit();
			tipoFactura = movimiento.getTipoFactura();
			nroFactura1 = null;
			nroFactura2 = null;
			if (!StringUtils.isBlank(movimiento.getNroFactura())) {
				nroFactura1 = movimiento.getNroFactura().substring(0, 4);
				nroFactura2 = movimiento.getNroFactura().substring(4, 12);
			}
			cuentaCod = movimiento.getHasta().getCodigo();
		}
		codMovimiento = 0L;
	}

	public void doConfirmar() {
		DAOFactoryJPA.getInstance().getMovimientoDAO().eliminarMovimiento(codMovimiento, getUsuarioLogueado().getApodo());
		actualizarLista();
		codMovimiento = 0L;
	}

	public void doConfirmarImporte() {
		Movimiento movimiento = DAOFactoryJPA.getInstance().getMovimientoDAO().findById(codMovimientoMod);
		movimiento.setImporte(importe);
		movimiento.setFecha(fecha);
		movimiento.setDetalle(detalle);
		movimiento.setZona(DAOFactoryJPA.getInstance().getZonaDAO().findById(codZonaMov));
		Cuenta cuenta = DAOFactoryJPA.getInstance().getCuentaDAO().findById(cuentaCod);
		if (movimiento.getTipoOperacion().getCodigo().equals(TipoOperacionEnum.ingreso.getCodigo())) {
			movimiento.setDesde(cuenta);
		} else {
			movimiento.setNroFactura(getNroFactura(nroFactura1, nroFactura2));
			movimiento.setNroCuit(cuit);
			movimiento.setTipoFactura(tipoFactura);
			movimiento.setHasta(cuenta);
		}
		DAOFactoryJPA.getInstance().getMovimientoDAO().persist(movimiento);
		codMovimientoMod = 0L;
		importe = 0D;
		fecha = null;
		detalle = null;
		codZonaMov = null;
		cuentaCod = null;
		cuit = null;
		nroFactura1 = null;
		nroFactura2 = null;
		limpiarTipoDeFactura();
		movimientos.clear();
		movimientos.add(movimiento);
	}

	private void limpiarTipoDeFactura() {	
		if (StringUtils.isBlank(nroFactura1) || StringUtils.isBlank(nroFactura2)) {
			tipoFactura = null;
		}
	}

	public Integer getCuentaCod() {
		return cuentaCod;
	}

	public void setCuentaCod(Integer cuentaCod) {
		this.cuentaCod = cuentaCod;
	}

	public void doCancelar() {
		codMovimiento = 0L;
		codMovimientoMod = 0L;
		importe = 0D;
		fecha = null;
		detalle = null;
		movimiento = null;
	}

	public boolean getShowButtons() {
		return codMovimiento > 0;

	}

	public boolean getShowButtonsMod() {
		return codMovimientoMod > 0;

	}

	private void actualizarLista() {
		for (Iterator<Movimiento> iterator = movimientos.iterator(); iterator.hasNext();) {
			Movimiento m = iterator.next();
			if (m.getCodigo().equals(codMovimiento)) {
				iterator.remove();
				break;
			}
		}
	}

	public Double getImporte() {
		return importe;
	}

	public void setImporte(Double importe) {
		this.importe = importe;
	}

	public List<Movimiento> getMovimientos() {
		return movimientos;
	}

	public void setMovimientos(List<Movimiento> movimientos) {
		this.movimientos = movimientos;
	}

	public void setFechaDesde(Date fechaDesde) {
		this.fechaDesde = fechaDesde;
	}

	public Date getFechaDesde() {
		return fechaDesde;
	}

	public void setFechaHasta(Date fechaHasta) {
		this.fechaHasta = fechaHasta;
	}

	public Date getFechaHasta() {
		return fechaHasta;
	}

	public void setCodZonaActual(Integer codZonaActual) {
		this.codZonaActual = codZonaActual;
	}

	public Integer getCodZonaActual() {
		return codZonaActual;
	}

	public void setZonasAsociadas(List<Zona> zonasAsociadas) {
		this.zonasAsociadas = zonasAsociadas;
	}

	public List<Zona> getZonasAsociadas() {
		return zonasAsociadas;
	}

	public Saldo getSaldo() {
		return saldo;
	}

	public void setSaldo(Saldo saldo) {
		this.saldo = saldo;
	}

	public Long getCodMovimiento() {
		return codMovimiento;
	}

	public void setCodMovimiento(Long codMovimiento) {
		this.codMovimiento = codMovimiento;
	}

	public void setMensaje(String mensaje) {
		this.mensaje = mensaje;
	}

	public String getMensaje() {
		return mensaje;
	}

	public void setCodMovimientoMod(Long codMovimientoMod) {
		this.codMovimientoMod = codMovimientoMod;
	}

	public Long getCodMovimientoMod() {
		return codMovimientoMod;
	}

	public void setFecha(Date fecha) {
		this.fecha = fecha;
	}

	public Date getFecha() {
		return fecha;
	}

	public void setDetalle(String detalle) {
		this.detalle = detalle;
	}

	public String getDetalle() {
		return detalle;
	}

	public void setCodZonaMov(Integer codZonaMov) {
		this.codZonaMov = codZonaMov;
	}

	public Integer getCodZonaMov() {
		return codZonaMov;
	}

	public void setCuentas(List<Cuenta> cuentas) {
		this.cuentas = cuentas;
	}

	public List<Cuenta> getCuentas() {
		return cuentas;
	}

	public String getNroFactura1() {
		return nroFactura1;
	}

	public void setNroFactura1(String nroFactura1) {
		this.nroFactura1 = nroFactura1;
	}

	public String getNroFactura2() {
		return nroFactura2;
	}

	public void setNroFactura2(String nroFactura2) {
		this.nroFactura2 = nroFactura2;
	}

	public TipoComprobanteEnum getTipoFactura() {
		return tipoFactura;
	}

	public void setTipoFactura(TipoComprobanteEnum tipoFactura) {
		this.tipoFactura = tipoFactura;
	}

	public String getCuit() {
		return cuit;
	}

	public void setCuit(String cuit) {
		this.cuit = cuit;
	}

	public Movimiento getMovimiento() {
		return movimiento;
	}

	public void setMovimiento(Movimiento movimiento) {
		this.movimiento = movimiento;
	}

	public void setSaldoCaja(Saldo saldoCaja) {
		this.saldoCaja = saldoCaja;
	}

	public Saldo getSaldoCaja() {
		return saldoCaja;
	}

}
